/*
*Copyright (c) Nikhil Jain.
*Project ICARUS, communications and 
*artificial intelligence.
*/



/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
 */
package javadrone.client.simulation;

//~--- non-JDK imports --------------------------------------------------------

import com.lti.civil.CaptureException;

import javadrone.RemoteImage;
import javadrone.State;

import javadrone.command.CommandExecutor;
import javadrone.command.ExecutionStatus;

import javadrone.remotepackage.RemoteBootPackage;

import javadrone.statedata.*;
import javadrone.statedata.ErrorData.ErrorState.ErrorFlag;

import javadrone.util.ImageStream;

//~--- JDK imports ------------------------------------------------------------

import java.rmi.RemoteException;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.vecmath.Vector3d;

/**
 *
 * @author Nikzzay
 */
public class GenericCommandExecutor implements CommandExecutor {
    private ImageStream     camFeed = new ImageStream();
    private ExecutorService pool    = Executors.newCachedThreadPool();
    private BotSimulator    bs;
    private State           droneState;

    public GenericCommandExecutor(State state) {
        this.droneState = state;
    }

    public GenericCommandExecutor(BotSimulator bs, State state) {
        this.bs         = bs;
        this.droneState = state;
    }

    @Override
    public void attach(BotSimulator bs) {
        this.bs = bs;
    }

    @Override
    public void translateBy(Vector3d translate) {
        updateNavigationState(bs.translateBy(translate));
    }

    @Override
    public void rotateBy(Vector3d rotate) {
        updateNavigationState(bs.rotateBy(rotate));
    }

    @Override
    public void setHover(boolean state) {
        updateAerialState(bs.setHover(state));
    }

    @Override
    public void setLanding(boolean state) {
        updateAerialState(bs.setLanding(true));
    }

    @Override
    public void kill() {
        updateBootState(bs.kill());
        pool.shutdownNow();
    }

    @Override
    public void boot(RemoteBootPackage rbp) {
        updateBootState(bs.boot(rbp));
    }

    @Override
    public void raiseError(ErrorFlag ef) {
        updateErrorState(bs.raiseError(ef));
    }

    @Override
    public void takeImage() {
        try {
            updateCamState(bs.takeImage());
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void startCamFeed() {
        try {
            bs.startFeed();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void stopCamFeed() {
        try {
            camFeed.stop();
        } catch (CaptureException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void raiseCollisionFlag() {
        updateCollisionState(bs.raiseCollisionFlag());
    }

    private void updateCamState(final RemoteImage ri) {
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    if (ri == null) {
                        return;
                    }

                    droneState.setStateData(new VideoCaptureStateData(new VideoCaptureStateData.VideoCaptureState(ri)));
                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    private void updateNavigationState(ExecutionStatus es) {
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    NavigationData.NavigationState ns = new NavigationData.NavigationState(bs.getCoords(),
                                                            bs.getAngles(), bs.isHovering(), bs.isLanding(),
                                                            bs.isAlive());

                    droneState.setStateData(new NavigationData(ns));
                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    private void updateBootState(ExecutionStatus es) {
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    droneState.setStateData(new BootData(new BootData.BootState(bs.bootState())));
                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    private void updateErrorState(ExecutionStatus es) {
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    droneState.setStateData(new ErrorData(new ErrorData.ErrorState(bs.errorState())));
                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    private void updateCollisionState(ExecutionStatus es) {
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    droneState.setStateData(
                        new CollisionStateData(new CollisionStateData.CollisionState(bs.hasCollided())));
                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    private void updateAerialState(ExecutionStatus es) {
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    droneState.setStateData(new AerialStateData(new AerialStateData.AerialState(bs.isHovering(),
                            bs.isLanding())));
                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }
}


//~ Formatted by Jindent --- http://www.jindent.com
